/*
    Contact info:
    bhepple@freeshell.org
    http://bhepple.freeshell.org/scrmgr

    Copyright (C) 1991-2008 Bob Hepple

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
#define SM_CLASS extern
#include "smlib.h"

CHAR *smwrite_rcsid(void) {
    return("$Id: smwrite.c,v 1.6 2008/02/19 13:15:50 bhepple Exp $");
}
    
static CHAR *sm_format_symbol ARG2(int, value, CHAR *, buf)
{
    CHAR	*s;

    s = sm_lookup_string(sm_keyword, value);
    if (s)
        buf += sprintf(buf, "%s%c", s, sm_default_separator);
    return(buf);
}

static int write_flag ARG2(CHAR *, buf, int, flag)
{
    return(sprintf(buf, "%c", flag? 'Y': 'N'));
}

CHAR *sm_format_file ARG2(SM_FILE, screenset, CHAR *, buf)
{
    assert(screenset);

    buf = sm_format_symbol(SM_FILE_F, buf);
    
    if (screenset->tagname) {
	strcpy(buf, screenset->tagname);
	buf = strchr(buf, 0);
    }
    *buf++ = sm_default_separator;

    if (screenset->separator == '\t')
	*buf++ = 't';
    else if (screenset->separator == 0)
	*buf++ = '0';
    else
	*buf++ = screenset->separator; /* careful! */
    *buf = 0;

    return(buf);
}

CHAR *sm_format_scr ARG3(SM_SCREEN, screen, CHAR *, buf, SM_SORTKEY, sortkey)
{
    int		i;
    CHAR	**a;

    assert(screen);

    buf = sm_format_symbol(SM_SCREEN_F, buf);
    
    for (i = 0; i < SM_NUM_SCR_FIELDS; i++) {
        switch (sm_wr_scr_line_order[i]) {

        case SM_NAME_F:
	    if (screen->screen_name)
                strcpy(buf, sm_trim(screen->screen_name));
            break;

        case SM_SCROLLING_F:
	    buf += write_flag(buf, screen->scrolling);
            break;

	case SM_CONSTANT_START_F:
	    if (screen->constant_start)
		strcpy(buf, screen->constant_start);
	    break;

	case SM_CONSTANT_END_F:
	    if (screen->constant_end)
		strcpy(buf, screen->constant_end);
	    break;

	case SM_FILENAME_F:
	    if (screen->filename)
		strcat(buf, screen->filename);
	    break;

	case SM_TEMP_STORAGE_F:
	    *buf++ = screen->temp_storage;
	    *buf = 0;
	    break;

	case SM_FIRST_FIELD_F:
	    if (screen->first_field)
		strcat(buf, screen->first_field);
	    break;

	case SM_SCREEN_SOFTKEY_F:
	    if (screen->softkey)
		strcat(buf, screen->softkey);
	    break;

	case SM_AUTO_ADJUST_F:
	    write_flag(buf, screen->auto_adjust);
	    break;

	case SM_SORT_FIELD_F:
	    if (sortkey && sortkey->sortfield_name && *sortkey->sortfield_name)
		strcat(buf, sortkey->sortfield_name);
	    break;

	case SM_SORT_IGNORE_CASE_F:
	    if (sortkey)
		write_flag(buf, sortkey->ignore_case);
	    break;

	case SM_SORT_MONTH_F:
	    if (sortkey)
		write_flag(buf, sortkey->month);
	    break;

	case SM_SORT_NUMERIC_F:
	    if (sortkey)
		write_flag(buf, sortkey->numeric);
	    break;

	case SM_SORT_REVERSE_F:
	    if (sortkey)
		write_flag(buf, sortkey->reverse);
	    break;

        case SM_SCREEN_FIELDNAMES_F:
	    if (!sortkey && screen->data_field) {
		a = (CHAR **) firstArrayItemp(screen->data_field);
		while (a && *a) {
		    strcpy(buf, *a);
		    a = (CHAR **) nextArrayItemp(screen->data_field, 
						 (void **) a);
		    buf = strchr(buf, 0);
		    *buf++ = sm_default_separator;
		    *buf = 0;
		}
		*--buf = 0;
	    }
            break;
        default:
            break;
        }
        buf = strchr(buf, 0);
        *buf++ = sm_default_separator;
        *buf = 0;
    }
    return(buf);
}

CHAR *sm_format_fld ARG2(SM_FIELD, field, CHAR *, buf)
{
    int i;

    assert(field);

    buf = sm_format_symbol(SM_FIELD_F, buf);
    
    for (i = 0; i < SM_NUM_FLD_FIELDS; i++) {
        switch (sm_wr_fld_line_order[i]) {
        case SM_NAME_F:
	    if (field->field_name)
		strcpy(buf, sm_trim(field->field_name));
            break;
        case SM_ROW_F:
            buf += sprintf(buf, "%d", field->row);
            break;
        case SM_COL_F:
            buf += sprintf(buf, "%d", field->col);
            break;
        case SM_ATTRIBUTE_F:
            buf += sprintf(buf, "%d", field->attribute);
            break;
        case SM_HIDDEN_F:
	    buf += write_flag(buf, field->hidden);
            break;
        case SM_PROTECT_F:
	    buf += write_flag(buf, field->protect);
            break;
        case SM_FTYPE_F:
            buf += sprintf(buf, "%d", 
			   field->ftype +
			   (field->non_blank? 100: 0) +
			   (field->has_popup? 200: 0) +
			   (field->disallow_chdir? 400: 
			    (field->disallow_insert? 400: 0)));
            break;
        case SM_LEN_F:
            buf += sprintf(buf, "%d", field->len);
            break;
        case SM_MAXLEN_F:
            buf += sprintf(buf, "%d", field->max_len);
            break;
        case SM_C_DEFAULT_F:
	    if (field->c_default)
		strcpy(buf, field->c_default);
            break;
	case SM_KEYSCREEN_F:
	    if (field->master_screen_name)
		strcpy(buf, field->master_screen_name);
	    break;
	case SM_TRIGGER_FN_F:
	    if (field->trigger_fn && *field->trigger_fn)
		strcpy(buf, field->trigger_fn);
	    break;
	case SM_NEXT_FIELD_F:
	    if (field->next_field)
		strcpy(buf, field->next_field);
	    break;
        default:
            break;
        }
        buf = strchr(buf, 0);
        *buf++ = sm_default_separator;
        *buf = 0;
    }
    return(buf);
}

CHAR *sm_format_bg ARG2(SM_BACKGROUND, bg, CHAR *, buf)
{
    int		i;

    assert(bg);

    /* Right trim the text */
    rTrimString(bg->text);
    
    buf = sm_format_symbol(SM_BG_F, buf);
    
    for (i = 0; i < SM_NUM_BG_FIELDS; i++) {
        switch (sm_wr_bg_line_order[i]) {
        case SM_TEXT_F:
            strcpy(buf, StringToStr(bg->text));
            break;
        case SM_ROW_F:
            buf += sprintf(buf, "%d", bg->row);
            break;
        default:
            break;
        }
        buf = strchr(buf, 0);
        *buf++ = sm_default_separator;
        *buf = 0;
    }
    return(buf);
}

/* Again - some rotten assumptions - 8 keys are assumed afer the keyset name;
   4 fields per key; only one field other than key entries; this sucks */
CHAR *sm_format_skey ARG2(SM_SOFTKEY, skey, CHAR *, buf)
{
    int	i, key_num;
    
    assert(skey);

    buf = sm_format_symbol(SM_KEY_F, buf);
    
    for (i = 0; i < SM_NUM_SKEY_FIELDS; i++) {
        key_num = (i - 1) / SM_NUM_FIELDS_PER_SKEY;
        switch (sm_wr_skey_line_order[i]) {
        case SM_NAME_F:
            strcpy(buf, sm_trim(skey->skey_name));
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
            break;
        case SM_UPPER_F:
            strncpy(buf, skey->upper[key_num], 8);
	    while (strlen(buf) < 8)
		strcat(buf, " ");
	    buf += 8;
	    *buf = 0;
            break;
        case SM_LOWER_F:
            strncpy(buf, skey->lower[key_num], 8);
	    while (strlen(buf) < 8)
		strcat(buf, " ");
	    buf += 8;
	    *buf = 0;
            break;
        case SM_KEY_NAME_F:
            strcpy(buf, skey->key_name[key_num]);
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
            break;
        case SM_TOGGLE_F:
            if (skey->toggle[key_num] == SM_NOT_TOGGLE)
		*buf++ = '0';
	    else
		*buf++ = '1';
	    *buf = 0;
            break;
        case SM_KEY_HELP_F:
	    if (skey->key_help[key_num]) {
		strcpy(buf, skey->key_help[key_num]);
		buf = strchr(buf, 0);
	    }
	    *buf++ = sm_default_separator;
	    *buf = 0;
            break;
        case SM_CALLBACK_FN_F:
	    if (skey->key_argument[key_num]) {
		strcpy(buf, skey->key_argument[key_num]);
		buf = strchr(buf, 0);
	    }
	    *buf++ = sm_default_separator;
	    *buf = 0;
            break;
        default:
            break;
        }
    }
    return(buf);
}

CHAR *sm_format_menu ARG3(SM_MENU, 		menu, 
			  int,			item,
			  CHAR *, 		buf)
{
    int	i;

    assert(menu);

    buf = sm_format_symbol(SM_MENU_F, buf);
    
    for (i = 0; i < SM_NUM_MENU_FIELDS; i++) {
	switch (sm_wr_menu_line_order[i]) {
	    
	case SM_NAME_F:
	    strcpy(buf, sm_trim(menu->menu_name));
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
	    break;
	    
	case SM_MENU_TYPE_F:
	    buf[0] = '0' + menu->type;
	    buf[1] = 0;
	    
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
	    break;
	    
	case SM_MENU_TEXT_F:
	    strcat(buf, ((SM_MENU_ITEM) arrayItem(menu->items,item))->text);
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
	    break;
	    
	case SM_MENU_COMMAND_F:
	    strcat(buf, ((SM_MENU_ITEM) arrayItem(menu->items,item))->command);
	    buf = strchr(buf, 0);
	    *buf++ = sm_default_separator;
	    *buf = 0;
	    break;
	    
	default:
	    break;
	}
    }
    return(buf);
}

/* Add backslashes to output (overwrites 'buf') and add ",\n to
   the end of every line. */
static int sm_fputs ARG2(CHAR *, buf, FILE *, f)
{
    CHAR	*backslash;

    while (*buf) {
	if ((backslash = strchr(buf, '\\')) != NULL)
	    *backslash = 0;
	if (fputs(buf, f) == EOF)
	    return(SM_ERROR);
	if (backslash) {
	    buf = backslash + 1;
	    if (fputs("\\\\", f) == EOF)
		return(SM_ERROR);
	} else
	    break;
    }
    if (fputs("\",\n", f) == EOF)
	return(SM_ERROR);
    return(0);
}

/*
 *
 * Write screen file - writes all screens & labels currently stored.
 *
 */

int sm_fwrite ARG2(SM_FILE,	screenset,
		   FILE *, 	f)
{
    SM_SCREEN		*screenp;
    SM_FIELD		*fieldp;
    SM_SOFTKEY		*skeyp;
    SM_MENU		*menup;
    SM_BACKGROUND	*bgp;
    int			i;
    CHAR		*buf, *pos;

#define FPUTS(x,y) if (sm_fputs((x),(y))) return(SM_ERROR)

    assert(screenset);

    buf = alloca(SM_MAXREC);

    sm_check_screens(screenset);

    sprintf(buf, "\"# Screen Manager Version %s", sm_version);
    FPUTS(buf, f);
   
    *buf = '\"';
    pos = sm_format_symbol(SM_FILE_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_FILE_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_file_line_order[i], pos);
    FPUTS(buf, f);
    
    *buf = '\"';
    pos = sm_format_symbol(SM_SCR_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_SCR_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_scr_line_order[i], pos);
    FPUTS(buf, f);
    
    *buf = '\"';
    pos = sm_format_symbol(SM_FLD_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_FLD_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_fld_line_order[i], pos);
    FPUTS(buf, f);
    
    *buf = '\"';
    pos = sm_format_symbol(SM_BG_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_BG_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_bg_line_order[i], pos);
    FPUTS(buf, f);
    
    *buf = '\"';
    pos = sm_format_symbol(SM_SKEY_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_SKEY_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_skey_line_order[i], pos);
    FPUTS(buf, f);

    *buf = '\"';
    pos = sm_format_symbol(SM_MENU_TABLE_F, buf + 1);
    for (i = 0; i < SM_NUM_MENU_FIELDS; i++)
        pos = sm_format_symbol(sm_wr_menu_line_order[i], pos);
    FPUTS(buf, f);

    *buf = '\"';
    sm_format_file(screenset, buf + 1);
    FPUTS(buf, f);

    screenp = sm_first_scr(screenset);
    while (screenp && *screenp) {
	if (((*screenp)->screen_name && *sm_trim((*screenp)->screen_name)) ||
	    (*screenp)->filename ||
	    sm_first_bg(*screenp) ||
	    sm_first_fld(*screenp)) {
	    SM_SORTKEY 		*sortkeyp;

	    *buf = '\"';
	    sm_format_scr(*screenp, buf + 1, NULL);
	    FPUTS(buf, f);

	    for (sortkeyp = sm_first_sortkey(*screenp); 
		 sortkeyp && *sortkeyp; 
		 sortkeyp = sm_next_sortkey(sortkeyp)) {
		*buf = '\"';
		sm_format_scr(*screenp, buf + 1, *sortkeyp);
		FPUTS(buf, f);
	    }
	    
	    bgp = sm_first_bg(*screenp);
	    while (bgp && *bgp) {
		if ((*bgp)->text) {
		    rTrimString((*bgp)->text);
		    if (StringLength((*bgp)->text) == 0) {
			bgp = sm_destroy_bg(bgp);
			continue;
		    }
		    *buf = '\"';
		    sm_format_bg(*bgp, buf + 1);
		    FPUTS(buf, f);
		}
		bgp = sm_next_bg(bgp);
	    }
	    fieldp = sm_first_fld(*screenp);
	    while (fieldp && *fieldp) {
		if (((*fieldp)->field_name && 
		     *sm_trim((*fieldp)->field_name)) ||
		    (*fieldp)->len) {
		    *buf = '\"';
		    sm_format_fld(*fieldp, buf + 1);
		    FPUTS(buf, f);
		}
		fieldp = sm_next_fld(fieldp);
	    }
	}
	screenp = sm_next_scr(screenp);
    }
    
    skeyp = sm_first_skey(screenset);
    while (skeyp && *skeyp) {
	if ( (*skeyp)->skey_name &&
	    *sm_trim((*skeyp)->skey_name)) {
	    *buf = '\"';
	    sm_format_skey(*skeyp, buf + 1);
	    FPUTS(buf, f);
	}
        skeyp = sm_next_skey(skeyp);
    }
    
    menup = sm_first_menu(screenset);
    while (menup && *menup) {
	if ( (*menup)->menu_name &&
	    *sm_trim((*menup)->menu_name)) {
	    INDEX	item;
	    
	    for (item = 0; item < arrayLength((*menup)->items); item++) {
		*buf = '\"';
		sm_format_menu(*menup, item, buf + 1);
		FPUTS(buf, f);
	    }
	}
	menup = sm_next_menu(menup);
    }
    
    return(0);
}

/* For emacs:
 * Local Variables:
 * tab-width: 8
 * End:
 */
